package com.fw.application.controller;


import cn.hutool.core.bean.BeanUtil;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fw.application.controller.base.BaseController;
import com.fw.common.AliComm;
import com.fw.common.IdXD;
import com.fw.enums.AliPayEnum;
import com.fw.enums.LogsModelEnum;
import com.fw.enums.LogsTypeEnum;
import com.fw.enums.OrderState;
import com.fw.mes.Result;
import com.fw.system.comm.service.DistrictService;
import com.fw.system.web.model.entity.*;
import com.fw.system.web.model.form.ReadyOrderForm;
import com.fw.system.web.model.form.ReadyOrderFormForm;
import com.fw.system.web.model.vo.AddrsVo;
import com.fw.system.web.service.*;
import com.github.pagehelper.PageHelper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.fw.mes.ResultUtils.success;

/**
 * <p>
 * 订单 前端控制器
 * </p>
 *
 * @since 2021-05-10
 */
@RestController
@RequestMapping("/order/")
@Api(tags = "订单")
@Slf4j
public class FwOrderController implements BaseController {

    private final IFwOrderService orderService;
    private final IFwParentOrderService parentOrderService;
    private final IFwSpuService spuService;
    private final IFwSkuService skuService;
    private final IdXD idXD;
    private final IFwLogsService logsService;
    private final IFwAddrsService addrsService;
    private final DistrictService districtService;
    private final IFwShopService shopService;
    private final IFwCartService cartService;
    private final AliComm aliComm;
    private final IFwUgJoinService ugJoinService;
    private final IFwMoneysService moneysService;
    private final FwGuessController guessController;
    private final IFwIdentityService identityService;

    public FwOrderController(IFwOrderService orderService,
                             IFwParentOrderService parentOrderService,
                             IFwSpuService spuService,
                             IFwSkuService skuService,
                             IdXD idXD, IFwUgJoinService ugJoinService,
                             IFwLogsService logsService, IFwAddrsService addrsService, DistrictService districtService,
                             IFwShopService shopService, IFwCartService cartService, AliComm aliComm,
                             IFwMoneysService moneysService, FwGuessController guessController,
                             IFwIdentityService identityService) {
        this.orderService = orderService;
        this.parentOrderService = parentOrderService;
        this.spuService = spuService;
        this.skuService = skuService;
        this.idXD = idXD;
        this.ugJoinService = ugJoinService;
        this.logsService = logsService;
        this.addrsService = addrsService;
        this.districtService = districtService;
        this.shopService = shopService;
        this.cartService = cartService;
        this.aliComm = aliComm;
        this.moneysService = moneysService;
        this.guessController = guessController;
        this.identityService = identityService;
    }

    /**
     * 我的订单列表-全部
     */
    @GetMapping("myOrderList/{pageNum}/{pageSize}")
    @ApiOperation("我的订单列表-1全部，0待付款，1待发货，2待收货,6确认收货，7申请售后")
    public Result<Map<String, Object>> myOrderList(@RequestParam(defaultValue = "-1") Integer orderState,
                                                   @RequestParam(defaultValue = "0") Integer afterSaleState,
                                                   @RequestParam(defaultValue = "-1") Integer isQuiz,
                                                   @PathVariable Integer pageNum,
                                                   @PathVariable Integer pageSize) {
        //获取小订单列表对应的，大订单id
        List<Object> parentOrderIdList = orderService.listObjs(Wrappers.<FwOrder>lambdaQuery()
                .select(FwOrder::getParentOrderId)
                .eq(!OrderState.ALL_ORDER.getCode().equals(orderState), FwOrder::getStatus, orderState)
                //全部中排除，申请售后
                .ne(OrderState.ALL_ORDER.getCode().equals(orderState), FwOrder::getStatus, OrderState.AFTER_SALE.getCode())
                .eq(afterSaleState != 0, FwOrder::getAfterSaleState, afterSaleState)
                .eq(FwOrder::getUserId, getUser().getId())
                //剔除删除的订单
                .eq(FwOrder::getRemoveFlag,0)
                //竞猜
//                .eq(isQuiz != -1, FwOrder::getIsQuiz, isQuiz)
                .groupBy(FwOrder::getParentOrderId));

        //防止为空时跳过 in
        if (parentOrderIdList.size() == 0) {
            parentOrderIdList.add("");
        }
        List<FwParentOrder> parentOrderList;
        PageHelper.startPage(pageNum, pageSize);
        parentOrderList = parentOrderService.list(Wrappers.<FwParentOrder>lambdaQuery()
                .eq(FwParentOrder::getUserId, getUser().getId())
//                    .eq(!OrderState.ALL_ORDER.getCode().equals(orderState), FwParentOrder::getState, orderState)
                .in(FwParentOrder::getParentOrderId, parentOrderIdList)
                //                .exists("select 1 from fw_order fo where parent_order_id = fo.parent_order_id ")
                .orderByDesc(FwParentOrder::getCreateTime));
//        }

        //最终的送回List
        List<FwParentOrder> newParentOrderList = new ArrayList<>();

        for (FwParentOrder parentOrder : parentOrderList) {
            //大订单为待支付
            if (OrderState.PENDING_PAYMENT.getCode().equals(parentOrder.getState())) {
                parentOrder.setOrderList(orderService.list(Wrappers.<FwOrder>lambdaQuery()
                        .eq(FwOrder::getParentOrderId, parentOrder.getParentOrderId())));
//                parentOrder.getOrderList().forEach(order -> orderService.perfectOrder(order));
                parentOrder.getOrderList().forEach(orderService::perfectOrder);
                parentOrder.setFwAddr(parentOrder.getOrderList().get(0).getFwAddr());
                parentOrder.setAddrString(parentOrder.getOrderList().get(0).getAddrString());
                newParentOrderList.add(parentOrder);
                continue;
            }
            //大订单非待支付
            List<FwOrder> orderList = orderService.list(Wrappers.<FwOrder>lambdaQuery()
                    .eq(FwOrder::getParentOrderId, parentOrder.getParentOrderId())
                    .orderByDesc(FwOrder::getCreateTime));
            //每个小订单，包装一层大订单
            for (FwOrder order : orderList) {
                order = orderService.perfectOrder(order);
                //填充订单详情
                order.setFwSpu(spuService.getById(order.getSpuId()));
                order.setFwSku(skuService.getById(order.getSkuId()));
                order.setFwAddr(addrsService.getVoById(order.getAddrId()));
                order.setFwShop(shopService.getById(order.getShopId()));
                //填充大订单
                FwParentOrder newParentOrder = new FwParentOrder();
                ArrayList<FwOrder> orderS = new ArrayList<>();
                orderS.add(order);
                newParentOrder.setParentOrderId(order.getId());
                newParentOrder.setParentOrderMoney(order.getTotalPrice());
                newParentOrder.setTotalFullPrice(order.getTotalFullPrice());
                newParentOrder.setShopping(order.getShopping());
                newParentOrder.setFullDiscount(order.getFullDiscount());
                newParentOrder.setOrderList(orderS);
                newParentOrder.setState(order.getStatus());
                newParentOrder.setCreateTime(order.getCreateTime());
                newParentOrder.setFwAddr(order.getFwAddr());
                newParentOrder.setAddrString(order.getAddrString());
                newParentOrderList.add(newParentOrder);
            }
        }
        Map<String, Object> resultMap = new HashMap<>(3);
        //小订单total
        int orderTotal = orderService.count(Wrappers.<FwOrder>lambdaQuery()
                .eq(!OrderState.ALL_ORDER.getCode().equals(orderState), FwOrder::getStatus, orderState)
                .eq(FwOrder::getUserId, getUser().getId()));
        resultMap.put("total", orderTotal);
        resultMap.put("data", newParentOrderList);
        return success(resultMap);
    }

    /**
     * 订单详情
     */
    @GetMapping("orderDetail/{id}")
    @ApiOperation("订单详情")
    public Result<FwParentOrder> orderDetail(@PathVariable String id) {
        FwOrder fwOrder = orderService.getById(id);
        FwParentOrder parentOrder = parentOrderService.getById(fwOrder.getParentOrderId());
        parentOrder.setOrderList(new ArrayList<>());
        orderService.perfectOrder(fwOrder);
        parentOrder.getOrderList().add(fwOrder);

        parentOrder.setParentOrderId(fwOrder.getId());
        parentOrder.setParentOrderMoney(fwOrder.getTotalPrice());
        parentOrder.setTotalFullPrice(fwOrder.getTotalFullPrice());
        parentOrder.setShopping(fwOrder.getShopping());
        parentOrder.setFullDiscount(fwOrder.getFullDiscount());
        parentOrder.setState(fwOrder.getStatus());
        parentOrder.setCreateTime(fwOrder.getCreateTime());
        parentOrder.setFwAddr(fwOrder.getFwAddr());
        parentOrder.setAddrString(fwOrder.getAddrString());
        return success(parentOrder);
    }

    /**
     * 大订单详情
     */
    @GetMapping("bigOrderDetail/{parentOrderId}")
    @ApiOperation("大订单详情")
    public Result<FwParentOrder> bigOrderDetail(@PathVariable String parentOrderId) {
        FwParentOrder parentOrder = parentOrderService.getById(parentOrderId);
        parentOrder.setOrderList(orderService.list(Wrappers.<FwOrder>lambdaQuery()
                .eq(FwOrder::getParentOrderId, parentOrder.getParentOrderId())));
        parentOrder.getOrderList().forEach(order -> {
            order.setFwSpu(spuService.getById(order.getSpuId()));
            order.setFwSku(skuService.getById(order.getSkuId()));
            order.setFwAddr(addrsService.getVoById(order.getAddrId()));
            order.setFwShop(shopService.getById(order.getShopId()));
        });
        parentOrder.setFwAddr(parentOrder.getOrderList().get(0).getFwAddr());
        parentOrder.setAddrString(parentOrder.getOrderList().get(0).getAddrString());
        return success(parentOrder);
    }

    /**
     * 提交订单
     */
    @PostMapping("submitOrder")
    @ApiOperation("提交订单")
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> submitOrder(@RequestBody ReadyOrderFormForm formForm) {
        List<FwShop> shopList = shopService.list(Wrappers.<FwShop>lambdaQuery().eq(FwShop::getUserId, getUser().getId()));
        List<ReadyOrderForm> formList = formForm.getFormList();
        //订单
        BigDecimal orderMoney = new BigDecimal(0);
        //运费
        BigDecimal shopping = new BigDecimal(0);
        //优惠
        BigDecimal fullAmount = new BigDecimal(0);

        //大订单
        FwParentOrder parentOrder = new FwParentOrder();
        parentOrder.setParentOrderId(idXD.nextId());
        parentOrder.setUserId(getUser().getId());
        parentOrder.setState(OrderState.PENDING_PAYMENT.getCode());
        parentOrder.setCreateTime(LocalDateTime.now());

        for (ReadyOrderForm form : formList) {
            FwSku fwSku = skuService.getById(form.getSkuId());
            FwSpu fwSpu = spuService.getById(fwSku.getSpuId());
            if (shopList != null && shopList.size() > 0) {
                for (FwShop shop:shopList) {
                    if (fwSpu.getShopId().equals(shop.getId())) {
                        return new Result<>().fail(1,"不能购买自己商铺的产品: "+fwSpu.getTitle());
                    }
                }
            }
            //判断库存是否充足
            if (fwSku.getSkuBalance() < form.getNumber()){
                return new Result<>().fail(100, fwSpu.getTitle() + fwSku.getSkuName() + "库存不足");
            }

            //小订单，商品金额
            BigDecimal smallOrderMoney = fwSku.getSkuMoney().multiply(new BigDecimal(form.getNumber()));
            //小订单满减
            BigDecimal smallFullAmount = new BigDecimal(0);
            //小订单运费
            BigDecimal smallShipping = new BigDecimal(0);

            //商品金额 * 数量
            orderMoney = orderMoney.add(smallOrderMoney);
            //是否满减
            if (orderMoney.compareTo(fwSpu.getFullStandard()) >= 0) {
                smallFullAmount = fwSpu.getFullAmount();
                fullAmount = fullAmount.add(smallFullAmount);
            }
            //是否免运费
//            if (fwSpu.getIsTopShipping() == 0 || orderMoney.compareTo(fwSpu.getTopShipping()) < 0) {
//                smallShipping = fwSpu.getShipping();
//                shopping = shopping.add(smallShipping);
//            }

            //生成临时地址Id
            FwAddrs orderAddr = addrsService.getById(form.getAddrId());
            orderAddr.setId(idXD.nextId());
            orderAddr.setUserId("");
            addrsService.save(orderAddr);

            //订单
            FwOrder order = new FwOrder();
            order.setId(idXD.nextId());
            order.setUserId(parentOrder.getUserId());
            order.setIsQuiz(0);
            order.setTotalPrice(smallOrderMoney.add(smallShipping).subtract(smallFullAmount));
            order.setTotalFullPrice(smallOrderMoney);
            order.setStatus(OrderState.PENDING_PAYMENT.getCode());
            order.setShopId(fwSpu.getShopId());
            order.setCreateTime(LocalDateTime.now());
            order.setParentOrderId(parentOrder.getParentOrderId());
            order.setSpuId(fwSpu.getId());
            order.setSkuId(fwSku.getId());
            order.setSpuNumber(form.getNumber());
            order.setAddrId(orderAddr.getId());
            order.setFullDiscount(smallFullAmount);
            //把地址放入order的字段中
            AddrsVo addr = addrsService.getVoById(order.getAddrId());
            order.setAddrString(addr.getContactName() + "&-fw-&" +
                    addr.getContactPhone() + "&-fw-&" +
                    addr.getProvinceName() +
                    addr.getAreaName() +
                    addr.getCityName() +
                    addr.getAddrInfo());
            orderService.save(order);

            //从购物车提交，清楚相应数据
            if (formForm.getIsCar() == 1) {
                cartService.remove(Wrappers.<FwCart>lambdaQuery()
                        .eq(FwCart::getUserId, getUser().getId())
                        .eq(FwCart::getSkuId, form.getSkuId()));
            }

            //减库存
            skuService.subtractBalance(order.getSkuId(), order.getSpuNumber());
            //加销量
            spuService.addTops(order.getSpuId(), order.getSpuNumber());
        }
        parentOrder.setParentOrderMoney(orderMoney.subtract(fullAmount));
        parentOrder.setTotalFullPrice(orderMoney);
        parentOrder.setShopping(shopping);
        parentOrder.setFullDiscount(fullAmount);
        parentOrderService.save(parentOrder);
        return success(parentOrder);
    }

    /**
     * 预订单
     */
    @PostMapping("readyOrder")
    @ApiOperation("预订单")
    public Result<Object> readyOrder(@RequestBody ReadyOrderFormForm formForm) {
        List<ReadyOrderForm> formList = formForm.getFormList();
        //订单
        BigDecimal orderMoney = new BigDecimal(0);
        //运费
        BigDecimal shopping = new BigDecimal(0);
        //优惠
        BigDecimal fullAmount = new BigDecimal(0);
        for (ReadyOrderForm form : formList) {
            FwSku fwSku = skuService.getById(form.getSkuId());
            FwSpu fwSpu = spuService.getById(fwSku.getSpuId());
            //商品金额 * 数量
            orderMoney = orderMoney.add(fwSku.getSkuMoney().multiply(new BigDecimal(form.getNumber())));
            if (orderMoney.compareTo(fwSpu.getFullStandard()) >= 0) {
                //达成满减，减运费
                fullAmount = fullAmount.add(fwSpu.getFullAmount());
            }
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("orderMoney", orderMoney);
        resultMap.put("shopping", shopping);
        resultMap.put("fullAmount", fullAmount);
        resultMap.put("overAmount", orderMoney.subtract(fullAmount));
        FwAddrs fwAddrs = addrsService.getOne(Wrappers.<FwAddrs>lambdaQuery().eq(FwAddrs::getUserId, getUser().getId())
                .eq(FwAddrs::getIsDefault, 1));
        AddrsVo addrsVo = new AddrsVo();
        BeanUtil.copyProperties(fwAddrs, addrsVo);
        if (fwAddrs != null){
            addrsVo.setAreaName(districtService.codeConversionName(fwAddrs.getArea()));
            addrsVo.setCityName(districtService.codeConversionName(fwAddrs.getCity()));
            addrsVo.setProvinceName(districtService.codeConversionName(fwAddrs.getProvince()));
        }
        resultMap.put("defaultAddr", addrsVo);
        return success(resultMap);
    }

    /**
     * @Effect 订单支付
     * @Author 姚
     * @Date 2021/6/11
     **/
    @GetMapping("payOrder/{parentOrderId}")
    @ApiOperation("订单支付-正式版")
    public Result<Object> payOrder(@PathVariable String parentOrderId) throws AlipayApiException {
        log.info("订单支付-正式版");
        FwParentOrder parentOrder = parentOrderService.getById(parentOrderId);
        if (!OrderState.PENDING_PAYMENT.getCode().equals(parentOrder.getState())) {
            return new Result<>().fail(1, "非待支付订单");
        }

        //竞猜订单
        List<FwOrder> orderList = orderService.list(Wrappers.<FwOrder>lambdaQuery()
                .eq(FwOrder::getParentOrderId, parentOrder.getParentOrderId()));
        for (FwOrder order : orderList){
            if (order.getIsQuiz() == 1){
                FwUgJoin ugJoin = ugJoinService.getOne(Wrappers.<FwUgJoin>lambdaQuery().eq(FwUgJoin::getOrderId, order.getId()));
                if ( !guessController.comeIn(ugJoin.getGuessId(), getUser().getId()) ) {
                    return new Result<>().fail(1, "竞猜房间不可加入");
                }
            }
        }

        String appPay = aliComm.appPay(parentOrder.getParentOrderId(),
                parentOrder.getParentOrderMoney(),
                AliPayEnum.SPU_ORDER_PAY);
        return success(appPay);
    }

    /**
     * @Effect 测试支付
     * @Author 姚
     * @Date 2021/6/11
     **/
    @GetMapping("payOrder/test/{parentOrderId}")
    @ApiOperation("订单支付-测试版")
    public Result<Object> payOrderTest(@PathVariable String parentOrderId)  {
        FwParentOrder parentOrder = parentOrderService.getById(parentOrderId);
        if (!OrderState.PENDING_PAYMENT.getCode().equals(parentOrder.getState())) {
            return new Result<>().fail(1, "非待支付订单");
        }

        List<FwOrder> orderList = orderService.list(Wrappers.<FwOrder>lambdaQuery()
                .eq(FwOrder::getParentOrderId, parentOrderId));
        if (OrderState.PENDING_PAYMENT.getCode().equals(parentOrder.getState())) {return success();}

        //状态修改
        parentOrderService.update(Wrappers.<FwParentOrder>lambdaUpdate()
                .set(FwParentOrder::getState, OrderState.TO_BE_DELIVERED.getCode())
                .eq(FwParentOrder::getParentOrderId, parentOrderId));
        orderList.forEach(order -> orderService.update(Wrappers.<FwOrder>lambdaUpdate()
                .set(FwOrder::getStatus, OrderState.TO_BE_DELIVERED.getCode())
                .set(FwOrder::getUpdateTime, LocalDateTime.now())
                .set(FwOrder::getPayType, OrderState.PAY_TYPE_ALI.getCode())//支付宝支付
                .eq(FwOrder::getId, order.getId())));
        return success();
    }

    /**
     * @Effect 确认收货
     * @Author 姚
     * @Date 2021/6/10
     **/
    @GetMapping("confirmReceipt/{orderId}")
    @ApiOperation("确认收货")
    public synchronized Result<Object> confirmReceipt(@PathVariable String orderId) {
        return orderService.confirmReceipt(orderId);
    }

    /**
     * @Effect 取消订单
     * @Author 姚
     * @Date 2021/6/11
     **/
    @GetMapping("cancelOrder/{parentOrderId}")
    @ApiOperation("取消订单")
    public Result<Object> cancelOrder(@PathVariable String parentOrderId) {
        FwParentOrder parentOrder = parentOrderService.getById(parentOrderId);
        if (parentOrder == null) { return new Result<>().fail(1,"未找到相应大订单"+parentOrderId); }
        if (OrderState.PENDING_PAYMENT.getCode().equals(parentOrder.getState())) {
            parentOrderService.removeById(parentOrderId);
            List<FwOrder> orderList = orderService.list(Wrappers.<FwOrder>lambdaQuery()
                    .eq(FwOrder::getParentOrderId, parentOrder.getParentOrderId()));

            orderList.forEach(order -> {
                //加库存
                skuService.addBalance(order.getSkuId(), order.getSpuNumber());
                //减销量
                spuService.subtractTops(order.getSpuId(), order.getSpuNumber());
            });

            //删小订单
            orderService.remove(Wrappers.<FwOrder>lambdaQuery()
                    .eq(FwOrder::getParentOrderId, parentOrder.getParentOrderId()));

            return success();
        }
        return new Result<>().fail(100, "仅待支付订单可取消");
    }

    /**
     * @Effect 修改订单收货地址
     * @Author 姚
     * @Date 2021/6/11
     **/
    @GetMapping("changeAddr/{orderIds}/{addrId}")
    @ApiOperation("修改订单收货地址")
    public Result<Object> changeAddr(@PathVariable String orderIds, @PathVariable String addrId) {
        String[] orderIdList = orderIds.split(",");
        //订单中存储的是临时地址
        FwAddrs fwAddrs = addrsService.getById(addrId);
        fwAddrs.setId(idXD.nextId());
        fwAddrs.setUserId("");

        addrsService.save(fwAddrs);
        for (String orderId : orderIdList) {
            FwOrder order = orderService.getById(orderId);
            if (order == null) {break;}

            order.setAddrId(fwAddrs.getId());
            //把地址放入order的字段中
            AddrsVo orderAddr = addrsService.getVoById(order.getAddrId());
            order.setAddrString(orderAddr.getContactName() + "&-fw-&" +
                    orderAddr.getContactPhone() + "&-fw-&" +
                    orderAddr.getProvinceName() +
                    orderAddr.getAreaName() +
                    orderAddr.getCityName() +
                    orderAddr.getAddrInfo());
            orderService.updateById(order);
        }
        return success();
    }

    /**
     * @Effect 申请退款
     * @Author 姚
     * @Date 2021/6/11
     **/
    @GetMapping("requestRefund/{orderId}")
    @ApiOperation("申请退款")
    public Result<Object> requestRefund(@PathVariable String orderId) {
        if (StringUtils.isEmpty(getUser().getAliPhone())) {
            return new Result<>().fail(1,"请先前往个人信息界面绑定支付宝账号");
        }
        FwOrder order = orderService.getById(orderId);
        if (order.getTotalPrice().compareTo(BigDecimal.ONE) < 0) {
            return new Result<>().fail(2,"金额小于一元不可线上退款，需要请联系客服");
        }
        order.setStatus(OrderState.AFTER_SALE.getCode());
        order.setAfterSaleState(OrderState.AFTER_SALE_APPLY.getCode());
        order.updateById();
        return success();
    }

    /**
     * @Effect 取消申请退款
     * @Author 姚
     * @Date 2021/6/20
     **/
    @GetMapping("cancelRequestRefund/{orderId}")
    @ApiOperation("取消申请退款")
    public Result<Object> cancelRequestRefund(@PathVariable String orderId){
        FwOrder fwOrder = orderService.getById(orderId);
        if (!fwOrder.getStatus().equals(OrderState.AFTER_SALE.getCode())) {
            return new Result<>().fail(1,"无需取消");
        }
        if (fwOrder.getCourierNumber()!=null) {
            fwOrder.setStatus(OrderState.TO_BE_RECEIVED.getCode());
        } else {
            fwOrder.setStatus(OrderState.TO_BE_DELIVERED.getCode());
        }
        orderService.updateById(fwOrder);
        return success();
    }

    /**
     * 提醒发货
     */
    @GetMapping("/pubPackage/{id}")
    @ApiOperation("提醒订单发货,订单编号")
    public Result pubPackage(@PathVariable String id){
        FwUser user = getUser();
        orderService.pubPackage(id,user);
        return success();
    }
}

